home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
news
/
readers
/
nn-tk.001
/
nn-tk~
/
nn
/
term.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-30
|
47KB
|
2,507 lines
/*
* (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
*
* Terminal interface.
*/
#define raw __curses__raw__
#include <signal.h>
#include <errno.h>
#include "config.h"
#include "keymap.h"
#include "regexp.h"
#include "nn_term.h"
#ifdef TK
#undef RESIZING
#endif /*TK*/
#ifdef RESIZING
#include <sys/ioctl.h> /* for TIOCGWINSZ */
#ifdef SYSV_RESIZING
#include <sys/stream.h>
#include <sys/ptem.h>
#endif /* SYSV_RESIZING */
extern int s_resized;
#endif /* RESIZING */
#ifdef FAKE_INTERRUPT
#include <setjmp.h>
#endif
#ifdef HAVE_TERMIOS
#include <termios.h>
#endif
#ifdef USE_TERMINFO
# ifdef HPUX80
# include <termio.h>
# endif /* HPUX80 */
# include <curses.h>
# ifndef VINTR
# include <termio.h> /* some systems don't include this in curses.h */
# endif /* VINTR */
# ifndef auto_left_margin
# include <term.h>
# endif /* !auto_left_margin */
#else
#define USE_TERMCAP
#ifdef __FreeBSD__
#include <termcap.h>
#endif
#endif
#ifdef HAVE_TERMIO
# ifdef USE_TERMCAP
# include <termio.h>
# endif /* USE_TERMCAP */
#else
#ifndef HAVE_TERMIOS
# include <sgtty.h>
#endif
#endif
/* SYSV curses.h clash */
#undef raw
/* term.c */
#ifdef __STDC__
static int outc __APROTO((char c));
#else
static int outc __APROTO(());
#endif
static void set_term_speed __APROTO((register unsigned long sp));
static void raw_not_ok_error __APROTO((void));
static sig_type rd_timeout __APROTO((int n));
static int read_char_kbd __APROTO((int tmo));
static void unread_char __APROTO((int c));
static sig_type catch_winch();
import int data_bits;
import int batch_mode;
import char *help_directory;
extern void ding();
extern void clrmsg();
extern void gotoxy();
struct msg_list {
char *buf;
struct msg_list *prev;
};
static struct msg_list *msg_stack = NULL, *msg_ptr = NULL;
export int message_history = 15;
export char *term_name = NULL;
export int show_current_time = 1;
export int conf_dont_sleep = 0;
export int prompt_length;
export int terminal_speed = 0;
export int slow_speed = 1200;
export int any_message = 0;
export int flow_control = 1;
export int use_visible_bell = 1; /* if supported by terminal */
export int ignore_xon_xoff = 1;
export int multi_key_guard_time = 2; /* tenths of a second */
export int guard_double_slash = 0; /* need /// or //+ to clear line */
export char *shade_on_attr = NULL;
export char *shade_off_attr = NULL;
export int mouse_state; /* if xterm is in mouse state */
export int mouse_usage; /* 0 don't set mouse, 1 only if xterm,
2 set mouse */
export key_type help_key = '?';
export key_type comp1_key = SP;
export key_type comp2_key = TAB;
export key_type erase_key, kill_key;
export key_type delword_key = CONTROL_('W');
static char bell_str[256] = "\007";
static appl_keypad_mode = 0;
#ifdef USE_TERMINFO
#define HAS_CAP(str) (str && *str)
extern char *tgoto(); /* some systems don't have this in term.h */
#else
char *tgoto();
char PC;
char *BC, *UP;
short ospeed;
static char XBC[64], XUP[64];
static char enter_ca_mode[64], exit_ca_mode[64];
static char cursor_home[64];
static char cursor_address[128];
static char clear_screen[64];
static char clr_eol[64];
static char clr_eos[64];
static char enter_standout_mode[64], exit_standout_mode[64];
static char enter_underline_mode[64], exit_underline_mode[64];
static char key_down[64], key_up[64], key_right[64], key_left[64];
static char keypad_local[64], keypad_xmit[64];
int magic_cookie_glitch; /* magic cookie size */
int ceol_standout_glitch; /* hp brain damage! */
int auto_right_margin; /* automatic right margin */
int eat_newline_glitch; /* newline ignored at right margin */
#define putp(str) tputs(str, 1, outc)
#define HAS_CAP(str) (*str)
#endif /* USE_TERMCAP */
static char key_mouse_d1[64] = "\33[M ";
static char key_mouse_d2[64] = "\33[M!";
static char key_mouse_d3[64] = "\33[M\"";
static char key_mouse_u1[64] = "\33[M#";
/*
* Compute the greatest multiple of p not greater than x.
* p must be a power of 2.
* x must be nonnegative, for portability to non-2's-complement hosts.
*/
#define DISCARD_REMAINDER(x,p) ((x) & ~((p)-1))
#ifdef __STDC__
static int
outc(char c)
#else
static int
outc(c) char c;
#endif
{
#ifndef TK
putchar(c);
#endif
return 0; /* XXX What is it supposed to return? */
}
#ifdef BROKEN_TPUTS
/* tputs is broken on UNISYS I've been told */
#define putpc(str, cnt) tputs(str, 0, outc)
#else
#define putpc(str, cnt) tputs(str, cnt, outc)
#endif
int Lines, Columns; /* screen size */
int cookie_size; /* size of magic cookie */
int two_cookies; /* space needed to enter&exit standout mode */
int STANDOUT; /* terminal got standout mode */
int curxy_c = 0, curxy_l = -1;
static int savxy_c = 0, savxy_l = -1;
static int just_sent_cr = 0; /* just sent \r to avoid 'xn' term attribute */
static int *nonsp; /* number of non-space characters on line */
#ifdef TERM_DEBUG
static char *term_debug = NULL;
extern char *getenv();
#define curxy_nonsp (curxy_l < 0 ? -1 : nonsp[curxy_l])
#endif
#ifdef FAKE_INTERRUPT
extern jmp_buf fake_keyb_sig;
extern int arm_fake_keyb_sig;
extern char fake_keyb_siglist[];
#endif /* FAKE_INTERRUPT */
#if defined(HAVE_TERMIO) || defined(HAVE_TERMIOS)
/* This used to be 50, but there are some rather complex bugs in the SYSV */
/* TERMIO driver... */
#define KEY_BURST 10 /* read bursts of 1 char (or timeout after 100 ms) */
#undef CBREAK
#ifdef HAVE_TERMIOS
static struct termios norm_tty, raw_tty;
#else
static struct termio norm_tty, raw_tty;
#endif
#define IntrC ((key_type) norm_tty.c_cc[VINTR])
#define EraseC ((key_type) norm_tty.c_cc[VERASE])
#define KillC ((key_type) norm_tty.c_cc[VKILL])
#ifdef HAVE_TERMIOS
#define SuspC ((key_type) norm_tty.c_cc[VSUSP])
#else
#define SuspC ((key_type) CONTROL_('Z')) /* norm_tty.c_cc[SWTCH] */
#endif
#else /* V7/BSD TTY DRIVER */
static struct sgttyb norm_tty, raw_tty;
static struct tchars norm_chars;
#define IntrC ((key_type) norm_chars.t_intrc)
#define EraseC ((key_type) norm_tty.sg_erase)
#define KillC ((key_type) norm_tty.sg_kill)
#ifdef TIOCGLTC
static struct ltchars spec_chars;
#define SuspC ((key_type) spec_chars.t_suspc)
#else
#define SuspC ((key_type) CONTROL_('Z'))
#endif
#endif
#ifdef USE_TERMCAP
opt_cap(cap, buf)
char *cap, *buf;
{
char *tgetstr();
*buf = NUL;
return tgetstr(cap, &buf) != NULL;
}
get_cap(cap, buf)
char *cap, *buf;
{
if (!opt_cap(cap, buf))
nn_exitmsg(1, "TERMCAP entry for %s has no '%s' capability",
term_name, cap);
}
#endif /* USE_TERMCAP */
/*
* timeout in n/10 seconds via SIGALRM
*/
void micro_alarm(n)
int n;
{
#ifdef HAVE_UALARM
ualarm(n<=1 ? 100000 : n*100000, 0); /* 4.3 BSD ualarm() */
#else
#ifdef MICRO_ALARM
if (n <= 0) n = 1;
MICRO_ALARM(n); /* System specific timeout */
#else
alarm(n <= 10 ? 1 : (n+9)/10); /* Standard alarm() call */
#endif /* MICRO_ALARM */
#endif /* HAVE_UALARM */
}
static int multi_keys = 0;
static struct multi_key {
key_type *cur_key;
key_type *keys;
key_type code;
} multi_key_list[MULTI_KEYS];
void enter_multi_key(code, keys)
int code;
key_type *keys;
{
register i;
if (strlen((char *)keys) == 1)
/* will ignore arrow keys overlaying these keys */
if (*keys == NL || *keys == CR ||
*keys == erase_key || *keys == kill_key ||
*keys == IntrC) return;
/* lookup code to see if it is already defined... */
for (i = 0; i < multi_keys; i++)
if (multi_key_list[i].code == (key_type)code)
goto replace_key;
i = multi_keys++;
/* now i points to matching or empty slot */
if (i >= MULTI_KEYS) {
/* should never happen */
log_entry('E', "too many multi keys");
return;
}
replace_key:
multi_key_list[i].keys = keys;
multi_key_list[i].code = code;
}
void dump_multi_keys()
{
register i;
register key_type *cp;
clrdisp();
tkb_clear();
tk("display_Make");
pg_init(0, 1);
for (i = 0; i < multi_keys; i++) {
if (pg_next() < 0) break;
tkb_tprintf("%d\t%s\t", i, key_name(multi_key_list[i].code));
for (cp = multi_key_list[i].keys; *cp; cp++)
tkb_tprintf(" %s", key_name(*cp));
tkb_c('\n');
tkb_display();
}
pg_end();
}
#ifdef RESIZING
static sig_type catch_winch(n)
int n;
{
struct winsize winsize;
int i;
(void) signal(SIGWINCH, catch_winch);
if (ioctl(0, TIOCGWINSZ, &winsize) >= 0
&& (winsize.ws_row != Lines || winsize.ws_col != Columns)) {
#ifndef TK
nonsp = resizeobj(nonsp, int, winsize.ws_row);
if ((int)winsize.ws_row > Lines)
for (i = Lines; i < (int)winsize.ws_row; i++) nonsp[i] = winsize.ws_col;
if ((int)winsize.ws_col < Columns)
for (i = 0; i < (int)winsize.ws_row; i++)
if (nonsp[i] > (int)winsize.ws_col) nonsp[i] = winsize.ws_col;
#endif
Lines = winsize.ws_row;
Columns = winsize.ws_col;
curxy_l = -1;
s_redraw = 1;
s_resized = 1;
}
#ifdef FAKE_INTERRUPT
if (fake_keyb_siglist[n] && arm_fake_keyb_sig)
longjmp(fake_keyb_sig, 1);
#endif /* FAKE_INTERRUPT */
}
#endif /* RESIZING */
#ifdef SV_INTERRUPT
#ifdef NO_SIGINTERRUPT
static siginterrupt(signo, on)
{
struct sigvec sv;
sv.sv_handler = signal (signo, SIG_DFL);
sv.sv_mask = 0;
sv.sv_flags = on ? SV_INTERRUPT : 0;
sigvec (signo, &sv, 0);
}
#endif /* NO_SIGINTERRUPT */
#endif /* SV_INTERRUPT */
#ifdef FAKE_INTERRUPT
#define SV_INTERRUPT
static siginterrupt (signo, on)
{
fake_keyb_siglist[signo] = on;
}
#endif /* FAKE_INTERRUPT */
static unsigned sp_table[] = {
#ifdef B115200
B115200, 11520,
#endif
#ifdef B57600
B57600, 5760,
#endif
B9600, 960,
#ifdef B19200
B19200, 1920,
#else
#ifdef EXTA
EXTA, 1920,
#endif /* EXTA */
#endif /* B19200 */
#ifdef B38400
B38400, 3840,
#else
#ifdef EXTB
EXTB, 3840,
#endif /* EXTB */
#endif /* B38400 */
B1200, 120,
B2400, 240,
B4800, 480,
B300, 30,
0, 0
};
static void set_term_speed(sp)
register unsigned long sp;
{
register unsigned *tp;
for (tp = sp_table; *tp; tp += 2)
if (*tp == sp) {
terminal_speed = tp[1];
return;
}
terminal_speed = 30;
}
static void raw_not_ok_error()
{
if (batch_mode) return;
nn_exitmsg(1, "Not prepared for terminal i/o");
/*NOTREACHED*/
}
#define RAW_CHECK if (terminal_speed == 0) {raw_not_ok_error(); return 0;}
#define RAW_CHECK_V if (terminal_speed == 0) {raw_not_ok_error(); return;}
#define BATCH_CHECK if (terminal_speed == 0) return 0
#define BATCH_CHECK_V if (terminal_speed == 0) return
void init_term(full)
int full;
{
#ifndef TK
#ifdef USE_TERMCAP
char tbuf[1024];
#endif
int i;
#ifdef TERM_DEBUG
term_debug = getenv("TERM_DEBUG");
if (term_debug) fprintf (stderr, "init_term(%d)\n", full);
#endif
if (batch_mode) {
term_name = "batch";
close(0);
open("/dev/null", 0);
STANDOUT = 0;
cookie_size = 1;
return;
}
if ((term_name = getenv("TERM")) == NULL) {
if (full)
nn_exitmsg(1, "No TERM variable in environment");
else
term_name = "unknown";
}
if (!full)
return;
#ifdef HAVE_TERMIO
ioctl(0, TCGETA, &norm_tty);
#else
#ifdef HAVE_TERMIOS
tcgetattr(0, &norm_tty);
#else
ioctl(0, TIOCGETP, &norm_tty);
#endif
#endif /* HAVE_TERMIO */
#ifdef USE_TERMINFO
setupterm((char *)NULL, 1, (int *)NULL);
Columns = columns;
Lines = lines;
if (use_visible_bell && HAS_CAP(flash_screen))
strcpy(bell_str, flash_screen);
else if (HAS_CAP(bell))
strcpy(bell_str, bell);
if (! HAS_CAP(cursor_home))
cursor_home = copy_str(tgoto(cursor_address, 0, 0));
#else
if (tgetent(tbuf, term_name) <= 0)
nn_exitmsg(1, "Unknown terminal type: %s", term_name);
if (opt_cap("bc", XBC)) BC = XBC;
if (opt_cap("up", XUP)) UP = XUP;
opt_cap("pc", cursor_address); /* temp. usage */
PC = cursor_address[0];
get_cap("cm", cursor_address);
if (!opt_cap("ho", cursor_home))
strcpy(cursor_home, tgoto(cursor_address, 0, 0));
get_cap("cl", clear_screen);
opt_cap("ce", clr_eol);
opt_cap("cd", clr_eos);
Lines = tgetnum("li");
Columns = tgetnum("co");
opt_cap("so", enter_standout_mode);
opt_cap("se", exit_standout_mode);
opt_cap("us", enter_underline_mode);
opt_cap("ue", exit_underline_mode);
opt_cap("kd", key_down);
opt_cap("ku", key_up);
opt_cap("kr", key_right);
opt_cap("kl", key_left);
magic_cookie_glitch = tgetnum("sg");
ceol_standout_glitch = tgetflag("xs");
auto_right_margin = tgetflag("am");
eat_newline_glitch = tgetflag("xn");
opt_cap("ti", enter_ca_mode);
opt_cap("te", exit_ca_mode);
opt_cap("ks", keypad_xmit); /* used to turn "application cursor */
opt_cap("ke", keypad_local); /* key" mode on and off (sometimes) */
if (!use_visible_bell || !opt_cap("vb", bell_str))
if (!opt_cap("bl", bell_str))
strcpy(bell_str, "\007");
#endif /* USE_TERMINFO */
#ifdef RESIZING
{
struct winsize winsize;
if (ioctl(0, TIOCGWINSZ, &winsize) >= 0
&& winsize.ws_row != 0 && winsize.ws_col != 0) {
Lines = winsize.ws_row;
Columns = winsize.ws_col;
(void) signal(SIGWINCH, catch_winch);
#ifdef SV_INTERRUPT
siginterrupt(SIGWINCH, 1); /* make read from tty interruptable */
#endif /* SV_INTERRUPT */
}
}
#endif /* RESIZING */
/* Stop NN from blowing up if on a *really* dumb terminal, like "dumb" */
if (Lines < 1)
Lines = 24;
if (Columns < 1)
Columns = 80;
nonsp = newobj(int, Lines);
for (i = 0; i < Lines; i++) nonsp[i] = Columns;
STANDOUT = HAS_CAP(enter_standout_mode);
cookie_size = magic_cookie_glitch;
if (STANDOUT) {
if (cookie_size < 0) cookie_size = 0;
two_cookies = 2 * cookie_size;
} else
cookie_size = two_cookies = 0;
raw_tty = norm_tty;
#ifdef HAVE_TERMIO
raw_tty.c_iflag &= ~(BRKINT|INLCR|ICRNL|IGNCR|ISTRIP);
raw_tty.c_iflag |= IGNBRK|IGNPAR;
raw_tty.c_oflag &= ~OPOST;
raw_tty.c_lflag &= ~(ISIG|ICANON|XCASE|ECHO|NOFLSH);
/* read a maximum of 10 characters in one burst; timeout in 1-200 ms */
raw_tty.c_cc[VMIN] = KEY_BURST;
raw_tty.c_cc[VTIME] = ((int)(raw_tty.c_cflag & CBAUD) > B1200) ? 1 : 2;
set_term_speed((unsigned long)(raw_tty.c_cflag & CBAUD));
#else
#ifdef HAVE_TERMIOS
cfmakeraw(&raw_tty);
/* read a maximum of 10 characters in one burst; timeout in 1-200 ms */
raw_tty.c_cc[VMIN] = KEY_BURST;
raw_tty.c_cc[VTIME] = (cfgetispeed(&raw_tty) > B1200) ? 1 : 2;
set_term_speed((unsigned long)cfgetospeed(&raw_tty));
#ifdef SV_INTERRUPT
siginterrupt(SIGTSTP, 1);
siginterrupt(SIGALRM, 1);
#endif /* SV_INTERRUPT */
#else
ioctl(0, TIOCGETC, &norm_chars);
#ifdef TIOCGLTC
ioctl(0, TIOCGLTC, &spec_chars);
#endif /* TIOCGLTC */
ospeed = norm_tty.sg_ospeed;
set_term_speed((unsigned long)ospeed);
raw_tty.sg_flags &= ~(ECHO | CRMOD);
#ifdef CBREAK
#ifdef SV_INTERRUPT /* make read from tty interruptable */
siginterrupt(SIGTSTP, 1); /* this is necessary to redraw screen */
#endif /* SV_INTERRUPT */
raw_tty.sg_flags |= CBREAK;
#else
raw_tty.sg_flags |= RAW;
#endif /* CBREAK */
#ifdef SV_INTERRUPT
siginterrupt(SIGALRM, 1); /* make read from tty interruptable */
#endif /* SV_INTERRUPT */
#endif
#endif /* HAVE_TERMIO */
erase_key = EraseC;
kill_key = KillC;
if (HAS_CAP(key_down))
enter_multi_key(K_down_arrow, (key_type *)key_down);
if (HAS_CAP(key_up))
enter_multi_key(K_up_arrow, (key_type *)key_up);
if (HAS_CAP(key_right))
enter_multi_key(K_right_arrow, (key_type *)key_right);
if (HAS_CAP(key_left))
enter_multi_key(K_left_arrow, (key_type *)key_left);
enter_multi_key(K_m_d1, (key_type *)key_mouse_d1);
enter_multi_key(K_m_d2, (key_type *)key_mouse_d2);
enter_multi_key(K_m_d3, (key_type *)key_mouse_d3);
enter_multi_key(K_m_u1, (key_type *)key_mouse_u1);
appl_keypad_mode = (HAS_CAP(keypad_xmit) && HAS_CAP(keypad_local));
if (!HAS_CAP(key_up)) appl_keypad_mode = 0; /* no cursor keys */
if (appl_keypad_mode) {
/* Use of ks/ke isn't consistent, so we must guess what to do. */
/* If termcap expects keys to send ESC [, don't switch */
appl_keypad_mode = (key_up[0] != '\033' || key_up[1] != '[');
}
if ((mouse_usage == 2) || ((mouse_usage == 1)
&& !strncmp("xterm",term_name,5))) {
mouse_state = 1;
flow_control = 0;
} else {
mouse_state = 0;
}
visual_on();
#else /* TK */
Columns=120;
terminal_speed=100000;
erase_key = 127;
#endif /* TK */
}
void
home()
{
BATCH_CHECK_V;
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, "home\n");
#endif
#ifndef TK
putp(cursor_home);
#endif /* TK */
curxy_c = curxy_l = 0;
}
void
save_xy()
{
savxy_c = curxy_c; savxy_l = curxy_l;
}
void
restore_xy()
{
if (savxy_l < 0) return;
gotoxy(savxy_c, savxy_l); fl;
}
void
gotoxy(c, l)
int c, l;
{
BATCH_CHECK_V;
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, "gotoxy %d %d -> %d %d\n", curxy_c, curxy_l, c, l);
#endif
#ifndef TK
if (Columns <= (unsigned)c || Lines <= (unsigned)l)
return;
if (!(c | l))
putp(cursor_home);
else
putp(tgoto(cursor_address, c, l));
#endif /* TK */
; curxy_c = c; curxy_l = l;
}
void
clrdisp()
{
int i;
BATCH_CHECK_V;
#ifndef TK
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, "clrdisp\n");
#endif
putpc(clear_screen, Lines);
curxy_c = curxy_l = 0;
savxy_l = -1;
for (i = 0; i < Lines; i++) nonsp[i] = 0;
msg_ptr = msg_stack;
#endif
}
void clrline_noflush();
void
tclrline()
{
BATCH_CHECK_V;
/* If we moved the cursor left to avoid weird effects, don't clear. */
if (just_sent_cr)
return;
clrline_noflush();
fl;
}
void
clrline()
{
tk_clrline();
tclrline();
}
void
clrline_noflush()
{
int oldxy_c, oldxy_l, spcnt;
BATCH_CHECK_V;
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, "clrline %d %d [%d]",curxy_c, curxy_l, curxy_nonsp);
#endif
if (curxy_l < 0)
return;
/* remainder of line already blank? */
#ifndef TK
if (curxy_c >= nonsp[curxy_l]) {
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, " ignored\n");
#endif
return;
}
if (HAS_CAP(clr_eol)) {
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, "\n");
#endif
putp(clr_eol);
} else {
oldxy_c = curxy_c; oldxy_l = curxy_l;
spcnt = nonsp[curxy_l] - curxy_c;
/* guard against scroll */
if (auto_right_margin && curxy_l == Lines-1 && curxy_c+spcnt == Columns)
spcnt--;
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr," %d\n", spcnt);
#endif /* TERM_DEBUG */
#ifdef TERM_DEBUG
if (term_debug && *term_debug) {
while (spcnt--) ttputc(*term_debug);
spcnt = 0;
}
#endif
/* clear out line */
while (spcnt--) ttputc(SP);
if (curxy_c != oldxy_c || curxy_l != oldxy_l)
gotoxy(oldxy_c, oldxy_l);
}
nonsp[curxy_l] = curxy_c;
#endif /* TK */
}
void
clrpage()
{
int oldxy_c, oldxy_l, i;
BATCH_CHECK_V;
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, "clrpage %d %d [%d]\n", curxy_c, curxy_l, curxy_nonsp);
#endif
#ifndef TK
if (curxy_l < 0)
return;
oldxy_c = curxy_c; oldxy_l = curxy_l;
/* code below only handles curxy_c == 0 */
if (curxy_c != 0) {
clrline();
if (curxy_l < Lines-1) gotoxy(0, curxy_l+1);
}
/* clear to end of screen */
if (curxy_c == 0) {
if (HAS_CAP(clr_eos)) {
putpc(clr_eos, Lines - curxy_l);
for (i = curxy_l; i < Lines; i++) nonsp[i] = 0;
} else if (curxy_l == 0) {
putpc(clear_screen, Lines);
for (i = 0; i < Lines; i++) nonsp[i] = 0;
} else {
for (i = curxy_l; i < Lines; i++) {
if (nonsp[i] != 0) {
gotoxy(0, i);
clrline_noflush();
}
}
}
}
if (curxy_c != oldxy_c || curxy_l != oldxy_l)
gotoxy(oldxy_c, oldxy_l);
fl;
msg_ptr = msg_stack;
#endif /* TK */
}
static char buf[512];
/*VARARGS*/
void ttprintf(va_alist)
va_dcl
{
use_vararg;
start_vararg;
tvprintf(va_args1toN);
end_vararg;
}
void tprintf(va_alist)
va_dcl
{
char buff[300];
char *fmt;
use_vararg;
start_vararg;
fmt = va_arg1(char *);
vsprintf(buff, fmt, va_args2toN);
tk_txt_a(buff);
end_vararg;
start_vararg;
tvprintf(va_args1toN);
end_vararg;
}
void tvprintf(va_tail)
va_tdcl
{
char *fmt, *str;
fmt = va_arg1(char *);
vsprintf(buf, fmt, va_args2toN);
for (str = buf; *str; str++)
ttputc(*str);
}
void tputc(c)
int c;
{
ttputc(c);
tk_txt_c(c);
}
void ttputc(c)
int c;
{
int i;
#ifdef TERM_DEBUG
if (term_debug) {
fprintf (stderr, "tputc %d %d [%d] ", curxy_c, curxy_l, curxy_nonsp);
if (c < ' ' || c > '~')
else
fprintf(stderr, "'%c'", c);
}
#endif
just_sent_cr = 0;
#ifndef TK
putchar(c);
#endif /* TK */
switch (c) {
case '\n':
curxy_c = 0;
if (curxy_l >= 0) curxy_l++;
break;
case '\r':
curxy_c = 0;
break;
case '\t':
curxy_c = DISCARD_REMAINDER(curxy_c + 8, 8);
break;
case '\b':
curxy_c--;
break;
case ' ':
curxy_c++;
#ifndef TK
if (curxy_l >= 0 && nonsp[curxy_l] == curxy_c)
nonsp[curxy_l]--;
#endif /* TK */
break;
default:
curxy_c++;
#ifndef TK
if (curxy_l >= 0 && nonsp[curxy_l] < curxy_c)
nonsp[curxy_l] = curxy_c;
#endif /* TK */
break;
}
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, " -> %d %d [%d]",curxy_c,curxy_l,curxy_nonsp);
#endif
/* account for right margin */
if (curxy_c == Columns) {
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, " margin");
#endif
if (auto_right_margin) {
if (eat_newline_glitch) {
#ifndef TK
putchar(CR);
#endif /* TK */
just_sent_cr = 1;
curxy_c = 0;
} else {
curxy_c = 0;
if (curxy_l >= 0) curxy_l++;
}
} else
curxy_c--;
}
/* account for vertical scroll */
if (curxy_l == Lines) {
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, " scroll");
#endif
#ifndef TK
for (i = 1; i < Lines; i++)
nonsp[i-1] = nonsp[i];
nonsp[--curxy_l] = 0;
#endif /* TK */
}
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, "\n");
#endif
}
static char so_buf[512], *so_p;
static int so_c, so_l, so_b, so_active = 0;
int so_gotoxy(c, l, blank)
int c, l, blank;
{
if (!STANDOUT && c >= 0) {
if (c>= 0 && l >= 0) gotoxy(c, l);
return 0;
}
#ifndef TK
so_active++;
so_c = c;
so_l = l;
so_b = blank;
so_p = so_buf;
*so_p = NUL;
#endif
return 1; /* not really true if not standout & c < 0 */
}
/*VARARGS*/
void so_printf(va_alist)
va_dcl
{
use_vararg;
start_vararg;
so_vprintf(va_args1toN);
end_vararg;
}
void so_vprintf(va_tail)
va_tdcl
{
char *fmt;
#ifndef TK
if (!so_active) {
if (ceol_standout_glitch) highlight(0); /* xxx why? */
tvprintf(va_args1toN);
return;
}
fmt = va_arg1(char *);
vsprintf(so_p, fmt, va_args2toN);
while (*so_p) so_p++;
#endif
}
void so_end()
{
int len;
if (!so_active) return;
#ifndef TK
if (so_l >= 0) {
len = so_p - so_buf + two_cookies;
if (so_c < 0)
so_c = Columns - len - 2;
if (so_c < 0) so_c = 0;
if (len + so_c >= Columns) {
len = Columns - so_c - two_cookies;
so_buf[len] = NUL;
}
if (cookie_size) {
gotoxy(so_c + len - cookie_size, so_l);
nn_standout(0);
}
gotoxy(so_c, so_l);
}
if ((so_b & 1) && (!STANDOUT || !cookie_size)) ttputc(SP);
if (STANDOUT) {
if (ceol_standout_glitch) clrline();
nn_standout(1);
}
ttprintf("%s", so_buf);
if (STANDOUT) nn_standout(0);
if ((so_b & 2) && (!STANDOUT || !cookie_size)) ttputc(SP);
so_active = 0;
#endif
}
/*VARARGS*/
void so_printxy(va_alist)
va_dcl
{
int c, l;
use_vararg;
start_vararg;
c = va_arg1(int);
l = va_arg2(int);
so_gotoxy(c, l, 0);
so_vprintf(va_args3toN);
so_end();
end_vararg;
}
int underline(on)
int on;
{
if (cookie_size) return 0;
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, "underline %d %d [%d] %d", curxy_c, curxy_l, curxy_nonsp, on);
#endif
#ifndef TK
if (! HAS_CAP(enter_underline_mode)) return 0;
putp(on ? enter_underline_mode : exit_underline_mode);
#endif
return 1;
}
int highlight(on)
int on;
{
if (cookie_size) return 0;
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, "highlight %d %d [%d] %d", curxy_c, curxy_l, curxy_nonsp, on);
#endif
#ifndef TK
if (! HAS_CAP(enter_standout_mode)) return 0;
putp(on ? enter_standout_mode : exit_standout_mode);
#endif
return 1;
}
int shadeline(on)
int on;
{
if (cookie_size) return 0;
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, "shadeline %d %d [%d] %d", curxy_c, curxy_l, curxy_nonsp, on);
#endif
#ifndef TK
if (shade_on_attr && shade_off_attr) {
putp(on ? shade_on_attr : shade_off_attr);
return 1;
} else
return underline(on);
#endif
}
int nn_standout(on)
int on;
{
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, "nn_standout %d %d [%d] %d", curxy_c, curxy_l, curxy_nonsp, on);
#endif
#ifndef TK
if (! HAS_CAP(enter_standout_mode)) return 0;
putp(on ? enter_standout_mode : exit_standout_mode);
curxy_c += cookie_size;
if (curxy_l >= 0 && curxy_c > nonsp[curxy_l])
nonsp[curxy_l] = curxy_c;
#ifdef TERM_DEBUG
if (term_debug)
fprintf(stderr, " -> %d %d [%d]\n", curxy_c, curxy_l, curxy_nonsp);
#endif
#endif
return 1;
}
static int is_visual = 0;
static int is_raw = 0;
#ifdef HAVE_TERMIO
#define RAW_MODE_ON ioctl(0, TCSETAW, &raw_tty)
#define RAW_MODE_OFF ioctl(0, TCSETAW, &norm_tty)
#else
#ifdef HAVE_TERMIOS
#define RAW_MODE_ON tcsetattr(0, TCSADRAIN, &raw_tty)
#define RAW_MODE_OFF tcsetattr(0, TCSADRAIN, &norm_tty)
#else
#define RAW_MODE_ON ioctl(0, TIOCSETP, &raw_tty)
#define RAW_MODE_OFF ioctl(0, TIOCSETP, &norm_tty)
#endif
#endif /* HAVE_TERMIO */
void
xterm_mouse_on()
{
putp("\33[?1000h");
}
void
xterm_mouse_off()
{
putp("\33[?1000l");
}
void
visual_on()
{
BATCH_CHECK_V;
if (terminal_speed == 0) return;
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, "visual_on\n");
#endif
#ifndef TK
if (!is_visual) {
if (HAS_CAP(enter_ca_mode)) putp(enter_ca_mode);
if (appl_keypad_mode) putp(keypad_xmit);
if (mouse_state)
xterm_mouse_on();
fl;
}
is_visual = 1;
#endif
}
int visual_off()
{
int was_raw = is_raw;
if (terminal_speed == 0) return 0;
#ifdef TERM_DEBUG
if (term_debug) fprintf(stderr, "visual_off\n");
#endif
#ifndef TK
if (is_visual) {
if (appl_keypad_mode) putp(keypad_local);
if (HAS_CAP(exit_ca_mode)) putp(exit_ca_mode);
if (mouse_state)
xterm_mouse_off();
fl;
}
is_visual = 0;
is_raw = 1;
unset_raw();
return was_raw;
#endif
}
#ifdef CBREAK
void
nn_raw()
{
#ifndef TK
RAW_CHECK_V;
if (is_raw == 1)
return;
is_raw = 1;
RAW_MODE_ON;
#endif /* TK */
}
int
no_raw()
{
return 0;
}
int
unset_raw()
{
#ifndef TK
if (is_raw == 0)
return 0;
RAW_CHECK;
RAW_MODE_OFF;
is_raw = 0;
#endif /* TK */
return 1;
}
#else /* not CBREAK */
static int must_set_raw = 1;
#undef raw
void
nn_raw()
{
#ifndef TK
RAW_CHECK_V;
if (!flow_control) {
if (!must_set_raw) return;
must_set_raw = 0;
}
if (is_raw) return;
RAW_MODE_ON;
is_raw++;
#endif /* TK */
}
int no_raw()
{
#ifndef TK
if (!flow_control) return 0;
if (!is_raw) return 0;
RAW_CHECK;
RAW_MODE_OFF;
is_raw = 0;
#endif /* TK */
return 1;
}
int unset_raw()
{
#ifndef TK
int was_raw = is_raw;
if (is_raw) {
RAW_CHECK;
RAW_MODE_OFF;
is_raw = 0;
}
if (!flow_control)
must_set_raw = 1;
return was_raw;
#endif /* TK */
}
#endif /* CBREAK */
#ifndef KEY_BURST
#define KEY_BURST 32
#endif /* KEY_BURST */
#define RD_PUSHBACK 10
static char rd_buffer[KEY_BURST+RD_PUSHBACK]; /* Holds stuff from read */
static char *rd_ptr;
static int rd_count = 0, rd_alarm = 0;
#ifdef FAKE_INTERRUPT
static jmp_buf fake_alarm_sig;
#endif /* FAKE_INTERRUPT */
static sig_type rd_timeout(n)
int n;
{
rd_alarm = 1;
#ifdef FAKE_INTERRUPT
longjmp(fake_alarm_sig, 1);
#endif /* FAKE_INTERRUPT */
}
#define RD_TIMEOUT 0x1000
#define RD_INTERRUPT 0x1001
static int read_char_kbd(tmo)
int tmo; /* timeout if no input arrives */
{
if (rd_count <= 0) {
if (tmo) {
#ifdef FAKE_INTERRUPT
if (setjmp(fake_alarm_sig)) goto tmout;
#endif /* FAKE_INTERRUPT */
rd_alarm = 0;
signal(SIGALRM, rd_timeout);
micro_alarm(multi_key_guard_time);
}
rd_ptr = rd_buffer + RD_PUSHBACK;
rd_count = read(0, rd_ptr, KEY_BURST);
if (tmo) {
if (rd_alarm) goto tmout;
alarm(0);
}
if (rd_count < 0) {
if (errno != EINTR) s_hangup++;
return RD_INTERRUPT;
}
}
--rd_count;
return *rd_ptr++;
tmout:
rd_count = 0;
return RD_TIMEOUT;
}
static void unread_char(c)
int c;
{
if (rd_ptr == rd_buffer) return;
rd_count++;
*--rd_ptr = c;
}
void
flush_input()
{
#ifndef TK
#ifndef HAVE_TERMIO
#ifdef FREAD
int arg;
#endif
#endif
BATCH_CHECK_V;
#ifdef HAVE_TERMIO
ioctl(0, TCFLSH, 0);
#else
#ifdef HAVE_TERMIOS
tcflush(0, TCIFLUSH);
#else
#ifdef FREAD
arg = FREAD;
ioctl(0, TIOCFLUSH, &arg);
#else
ioctl(0, TIOCFLUSH, 0);
#endif /* FREAD */
#endif
#endif /* HAVE_TERMIO */
rd_count = 0;
#endif /* TK */
}
int enable_stop = 1;
int do_macro_processing = 1;
export int mouse_x,mouse_y = -1;
static int mouse_last = 0;
#ifndef TK
int get_c()
{
key_type c, first_key;
int key_cnt, mc, n;
register struct multi_key *mk, *multi_match;
register int i;
multi_match = NULL;
first_key = 0;
mouse_y = -1;
next_key:
if (s_hangup) return K_interrupt;
if (do_macro_processing)
switch (m_getc(&mc)) {
case 0: break;
case 1: return mc;
case 2: return K_interrupt;
}
#ifdef RESIZING
if (s_resized) goto redraw;
#endif /* RESIZING */
if (batch_mode)
nn_exitmsg(1, "Attempt to read keyboard input in batch mode");
for (i = multi_keys, mk = multi_key_list; --i >= 0; mk++)
mk->cur_key = mk->keys;
key_cnt = 0;
#ifdef FAKE_INTERRUPT
if (setjmp(fake_keyb_sig)) goto intr;
arm_fake_keyb_sig = 1;
#endif /* FAKE_INTERRUPT */
multi:
switch (n = read_char_kbd(key_cnt)) {
case RD_INTERRUPT:
#ifdef CBREAK
if (s_redraw) goto redraw;
#endif /* CBREAK */
#ifdef RESIZING
if (s_resized) goto redraw;
#endif /* RESIZING */
goto intr;
case RD_TIMEOUT:
while (--key_cnt > 0) unread_char(multi_match->keys[key_cnt]);
c = first_key;
goto got_char;
default:
c = (key_type)n;
if (data_bits < 8) c &= 0x7f;
if (ignore_xon_xoff)
if (c == CONTROL_('Q') || c == CONTROL_('S')) goto multi;
break;
}
multi_match = NULL;
for (i = multi_keys, mk = multi_key_list; --i >= 0; mk++) {
if (mk->cur_key == NUL) continue;
if (*(mk->cur_key)++ != c) {
mk->cur_key = NUL;
continue;
}
if (*(mk->cur_key) == NUL) {
c = mk->code;
/* xterm mouse specific code, translate cursor position
into static variables, synthesize key up events */
if ((c >= K_m_d1) && (c <= K_m_u1)) {
mouse_x = read_char_kbd(key_cnt) - '!';
mouse_y = read_char_kbd(key_cnt) - '!';
if (c == K_m_u1) {
if (mouse_last == K_m_d2) {
c = K_m_u2;
} else if (mouse_last == K_m_d3) {
c = K_m_u3;
}
}
mouse_last = c;
}
goto got_char;
}
multi_match = mk;
}
if (multi_match) {
if (key_cnt == 0) first_key = c;
key_cnt++;
goto multi;
}
if (key_cnt) {
if (key_cnt == 1 && first_key == 033) {
unread_char(c);
c = 033;
goto got_char;
}
ding();
flush_input();
goto next_key;
}
got_char:
#ifdef FAKE_INTERRUPT
arm_fake_keyb_sig = 0;
#endif /* FAKE_INTERRUPT */
c = global_key_map[c];
#ifndef CBREAK
if (c == IntrC) return K_interrupt; /* don't flush */
if (c == SuspC) {
if (enable_stop && suspend_nn()) goto redraw;
goto next_key;
}
#endif /* CBREAK */
return (int)c;
intr:
#ifdef FAKE_INTERRUPT
arm_fake_keyb_sig = 0;
#endif /* FAKE_INTERRUPT */
rd_count = 0;
return K_interrupt;
redraw:
#ifdef RESIZING
s_resized = 0;
#endif /* RESIZING */
s_redraw = 0;
return GETC_COMMAND | K_REDRAW;
}
#endif /* TK */
/*
* read string with completion, pre-filling, and break on first char
*
* dflt is a string that will be use as default value if the
* space bar is hit as the first character.
*
* prefill pre-fill the buffer with .... and print it
*
* break_chars return immediately if one of these characters
* is entered as the first character.
*
* completion is a function that will fill the buffer with a value
* see the group_completion and file_completion routines
* for examples.
*/
char *get_s(dflt, prefill, break_chars, completion)
char *dflt, *prefill, *break_chars;
fct_type completion;
{
static key_type lbuf[GET_S_BUFFER];
register char *cp;
int i, c, lastc;
char *ret_val = (char *)lbuf;
int comp_used, comp_len;
int ostop, max, did_help;
int hit_count;
switch (m_gets((char *)lbuf)) {
case 0:
break;
case 1:
return (char *)lbuf;
case 2:
return NULL;
}
ostop = enable_stop;
enable_stop = 0;
do_macro_processing = 0;
hit_count = 0;
max = Columns - prompt_length;
if (max >= FILENAME) max = FILENAME-1;
i = comp_len = comp_used = did_help = 0;
if (prefill && prefill[0]) {
while ((c = *prefill++)) {
if (i == max) break;
tputc(c);
lbuf[i] = c;
i++;
}
fl;
}
if (dflt && *dflt == NUL)
dflt = NULL;
if (break_chars && *break_chars == NUL)
break_chars = NULL;
c = NUL;
for(;;) {
lastc = c;
c = get_c();
if (c & GETC_COMMAND) continue;
kill_prefill_hack:
hit_count++;
if (i == 0) {
if (c == comp1_key && dflt) {
while ((c = *dflt++) != NUL && i < max) {
tputc(c);
lbuf[i] = c;
i++;
}
fl;
dflt = NULL;
continue;
}
if ((cp = break_chars)) { /* Stupid ^@$# GCC!!! */
while (*cp)
if (*cp++ == c) {
lbuf[0] = c;
lbuf[1] = NUL;
goto out;
}
}
}
if (completion != NULL_FCT) {
if (comp_used && c == erase_key) {
if (comp_len) {
i -= comp_len;
while (--comp_len >= 0) tputc(BS);
clrline();
}
if (!CALL(completion)(lbuf, -(i+1)) && did_help)
clrmsg(i);
did_help = 0;
comp_len = comp_used = 0;
if (lastc == help_key) goto no_completion;
continue;
}
if (c == comp1_key || c == comp2_key || c == help_key) {
if (!comp_used || c == comp2_key ||
(c == help_key && lastc != c)) {
lbuf[i] = NUL;
if ((comp_used = CALL(completion)(lbuf, i)) == 0) {
ding();
continue;
}
if (comp_used < 0) {
comp_used = 0;
goto no_completion;
}
comp_len = 0;
}
if (c == help_key) {
if (CALL(completion)((char *)NULL, 1)) {
gotoxy(prompt_length+i, prompt_line); fl;
did_help = 1;
}
continue;
}
if (comp_len) {
i -= comp_len;
while (--comp_len >= 0) tputc(BS);
clrline();
comp_len = 0;
}
switch ( CALL(completion)((char *)NULL, 0) ) {
case 0: /* no possible completion */
comp_used = 0;
ding();
continue;
case 2: /* whole new alternative */
while (--i >= 0) tputc(BS);
clrline();
/*FALLTHRU*/
case 1: /* completion */
comp_len = i;
while ((c = lbuf[i])) {
if (i == max) break;
tputc(c);
i++;
}
fl;
comp_len = i - comp_len;
continue;
}
}
if (comp_used) {
if (!CALL(completion)(lbuf, -(i+1)) && did_help)
clrmsg(i);
did_help = 0;
comp_len = comp_used = 0;
}
}
no_completion:
if (c == CR || c == NL) {
lbuf[i] = NUL;
break;
}
if (c == erase_key) {
if (i <= 0) continue;
i--;
tputc(BS);
tputc(' ');
tputc(BS);
fl;
continue;
}
if (c == delword_key) {
if (i <= 0) continue;
lbuf[i-1] = 'X';
while (i > 0 && isalnum(lbuf[i-1])) { tputc(BS); i--; }
clrline();
continue;
}
if (c == kill_key) {
while (i > 0) { tputc(BS); i--; }
clrline();
if (hit_count == 1 && dflt) {
c = comp1_key;
goto kill_prefill_hack;
}
continue;
}
if (c == K_interrupt) {
ret_val = NULL;
break;
}
if (data_bits == 8) {
if (!iso8859(c)) continue;
} else
if (!isascii(c) || !isprint(c)) continue;
if (i == max) continue;
if (i > 0 && lbuf[i-1] == '/' && (c == '/' || c == '+')) {
if (c != '/' || !guard_double_slash || (i > 1 && lbuf[i-2] == '/')) {
if (completion == file_completion) {
while (i > 0) { tputc(BS); i--; }
clrline();
}
}
}
tputc(c);
fl;
lbuf[i] = c;
i++;
}
out:
enable_stop = ostop;
do_macro_processing = 1;
return ret_val;
}
export int list_offset = 0;
int list_completion(str)
char *str;
{
static int cols, line;
if (str == NULL) {
cols = Columns;
line = prompt_line + 1;
if (line == Lines - 1) cols--;
gotoxy(0, line);
clrpage();
return 1;
}
str += list_offset;
for (;;) {
cols -= strlen(str);
if (cols >= 0) {
tprintf("%s%s", str, cols > 0 ? " " : "");
cols--;
return 1;
}
if (line >= Lines - 1) return 0;
line++;
cols = Columns;
gotoxy(0, line);
if (line == Lines - 1) cols--;
}
}
int yes(must_answer)
int must_answer;
{
int c, help = 1, in_macro = 0;
switch (m_yes()) {
case 0:
break;
case 1:
return 0;
case 2:
return 1;
case 3:
do_macro_processing = 0;
in_macro++;
break;
}
fl;
for (;;) {
if (!is_raw) {
nn_raw();
c = get_c();
unset_raw();
} else
c = get_c();
if (c == 'y' || c == 'Y') {
c = 1;
break;
}
if (must_answer == 0 && (c == SP || c == CR || c == NL)) {
c = 1;
break;
}
if (c == 'n' || c == 'N') {
c = 0;
break;
}
if (c == K_interrupt) {
c = -1;
break;
}
if (help) {
tprintf(" y=YES n=NO"); fl;
prompt_length += 11;
help = 0;
}
}
if (in_macro) {
if (c < 0) m_break();
do_macro_processing = 1;
}
tk("y_destroy");
return c;
}
void
ding()
{
BATCH_CHECK_V;
putp(bell_str);
fl;
}
void display_file(name, modes)
char *name;
int modes;
{
FILE *f;
register c, stand_on;
int linecnt, headln_cnt, hdline, no_conf;
char headline[128];
int cnt = 0;
tkb_clear();
headline[0] = 0;
hdline = 0;
no_conf = 0;
headln_cnt = -1;
if (modes & CLEAR_DISPLAY) {
gotoxy(0,0);
clrdisp();
}
#ifdef TK
linecnt = 500;
#else /* TK */
linecnt = Lines - 1;
#endif /* TK */
chain:
if (*name != '/') name = relative(help_directory, name);
f = open_file(name, OPEN_READ);
if (f == NULL) {
ttprintf("\r\n\n");
tprintf("File %s is not available", name);
ttprintf("\n\n");
if (!no_conf && (modes & CONFIRMATION))
any_key(prompt_line);
return;
} else {
stand_on = 0;
if (!cnt)
tk("display_Make");
cnt++;
while ((c = getc(f)) != EOF) {
#ifdef HAVE_JOBCONTROL
if (s_redraw) {
no_conf = 1;
break;
}
#endif /* HAVE_JOBCONTROL */
no_conf = 0;
if (c == '\1') {
tkb_c(1);
if (STANDOUT) {
putp(stand_on ? exit_standout_mode : enter_standout_mode);
curxy_c += cookie_size;
stand_on = !stand_on;
}
continue;
}
if (c == '\2') {
headln_cnt = 0;
continue;
}
if (c == '\3') {
headln_cnt = 0;
while ((c = getc(f)) != EOF && c != NL)
headline[headln_cnt++] = c;
headline[headln_cnt++] = NUL;
name = headline;
fclose(f);
goto chain;
}
if (c == '\4') {
tkb_tprintf("%s", version_id);
continue;
}
if (headln_cnt >= 0)
headline[headln_cnt++] = c;
if (hdline) {
tkb_tprintf("%s\r", headline);
hdline = 0;
linecnt--;
}
tkb_ttputc(c);
if (c == NL) {
ttputc(CR);
tkb_c(0);
tkb_display();
if (headln_cnt >= 0) {
headline[--headln_cnt] = 0;
headln_cnt = -1;
}
if (--linecnt == 0) {
no_conf = 1;
if (any_key(0) == K_interrupt)
break;
linecnt = Lines - 1;
if (modes & CLEAR_DISPLAY) {
gotoxy(0,0);
clrdisp();
}
hdline = headline[0];
}
}
}
if (stand_on) {
putp(exit_standout_mode);
curxy_c += cookie_size;
}
fclose(f);
}
prompt_line = Lines-1; /* move prompt to last line */
#ifndef TK
if (!no_conf && (modes & CONFIRMATION))
any_key(prompt_line);
#endif /* TK */
}
/*VARARGS*/
void nn_exitmsg(va_alist)
va_dcl
{
char *fmt;
int n;
use_vararg;
if (terminal_speed != 0) {
clrdisp();
visual_off();
}
start_vararg;
n = va_arg1(int);
fmt = va_arg2(char *);
vprintf(fmt, va_args3toN);
putchar(NL);
end_vararg;
nn_exit(n);
/*NOTREACHED*/
}
/*VARARGS*/
void msg(va_alist)
va_dcl
{
use_vararg;
start_vararg;
vmsg(va_args1toN);
#ifdef TK
tk("update");
sleep(1);
#endif /* TK */
end_vararg;
}
void push_msg(str)
char *str;
{
register struct msg_list *mp, *newmsg;
static int slots = 0;
if (str != NULL) {
if (slots > message_history) {
for (mp = newmsg = msg_stack; mp->prev != NULL; mp = mp->prev)
newmsg = mp;
if (newmsg == mp)
msg_stack = NULL;
else {
newmsg->prev = NULL;
newmsg = mp;
}
freeobj(newmsg->buf);
} else {
slots++;
newmsg = newobj(struct msg_list, 1);
}
newmsg->buf = copy_str(str);
newmsg->prev = msg_stack;
msg_stack = newmsg;
}
msg_ptr = msg_stack;
}
void vmsg(va_tail)
va_tdcl
{
char *errmsg, *fmt;
fmt = va_arg1(char *);
if (fmt) {
char lbuf[512];
vsprintf(lbuf, fmt, va_args2toN);
push_msg(lbuf);
}
if (msg_ptr) {
errmsg = msg_ptr->buf;
msg_ptr = msg_ptr->prev;
} else {
errmsg = "(no more messages)";
msg_ptr = msg_stack;
}
if (terminal_speed == 0) {
tprintf("%s\n", errmsg);
fl;
return;
}
gotoxy(0, Lines-1);
tprintf("%s", errmsg);
clrline();
any_message = 1;
if (prompt_line != Lines-1)
gotoxy(prompt_length, prompt_line);
fl;
}
void
clrmsg(col)
int col;
{
BATCH_CHECK_V;
gotoxy(0, prompt_line + 1);
clrpage();
if (col >= 0)
gotoxy(prompt_length + col, prompt_line);
fl;
any_message = 0;
}
/*VARARGS*/
void
prompt(va_alist)
va_dcl
{
register char *cp;
int stand_on;
char *fmt;
static char cur_p[FILENAME];
static char saved_p[FILENAME];
use_vararg;
prompt_clear();
tkb_clear();
BATCH_CHECK_V;
start_vararg;
fmt = va_arg1(char *);
if (fmt == P_VERSION) {
gotoxy(0, prompt_line + 1);
tprintf("Release %s ", version_id);
clrline();
any_message++;
if (prompt_line >= 0)
gotoxy(prompt_length, prompt_line);
goto out;
}
if (fmt == P_SAVE) {
strcpy(saved_p, cur_p);
goto out;
}
if (fmt == P_RESTORE)
strcpy(cur_p, saved_p);
if (prompt_line >= 0)
gotoxy(0, prompt_line);
if (fmt == P_MOVE) {
clrline();
goto out;
}
if (fmt != P_REDRAW && fmt != P_RESTORE)
vsprintf(cur_p, fmt, va_args2toN);
tputc(CR);
for (cp = cur_p, stand_on = 0, prompt_length = 0; *cp; cp++) {
if (*cp == '\1') {
if (cp[1] != '\1') {
if (STANDOUT) {
stand_on = !stand_on;
nn_standout(stand_on);
prompt_length += cookie_size;
}
continue;
}
cp++;
} else
if (*cp == '\2') {
time_t t;
char *timestr;
t = tick_usage();
if (show_current_time) {
timestr = ctime(&t) + 11;
timestr[5] = NUL;
tkb_tprintf("-- %s ", timestr);
prompt_length += 9;
}
if (unread_mail(t)) {
tkb_tprintf("Mail ");
prompt_length += 5;
}
continue;
}
tkb_ttputc(*cp);
prompt_length ++;
}
if (stand_on) {
nn_standout(0);
prompt_length += cookie_size;
}
clrline();
tkb_txt_a();
if (fmt == P_RESTORE)
restore_xy();
#if notdef
else
curxy_c = -1;
#endif
out:
end_vararg;
tk_c_normal_prompt();
}
int any_key(line)
int line;
{
int was_raw, c, dmp;
BATCH_CHECK;
was_raw = is_raw;
if (!is_raw) nn_raw();
if (line == 0)
line = -1;
else
if (line < 0)
line = Lines + line;
if (line != 10000) {
so_printxy(0, line, "Hit any key to continue");
tk_txt_a("Hit any key to continue");
}
#ifndef TK
clrline();
#endif /* TK */
dmp = do_macro_processing;
do_macro_processing = 0;
c = get_c();
if (c == 'q' || c == 'Q') c = K_interrupt;
do_macro_processing = dmp;
if (!was_raw) unset_raw();
return c;
}
static pg_fline, pg_width, pg_maxw, pg_line, pg_col, pg_quit;
export regexp *pg_regexp = NULL;
export int pg_new_regexp = 0;
void pg_init(first_line, cols)
int first_line, cols;
{
if (pg_regexp) {
freeobj(pg_regexp);
pg_regexp = NULL;
}
pg_new_regexp = 0;
pg_fline = first_line;
pg_line = pg_fline - 1;
pg_quit = pg_col = 0;
pg_width = Columns / cols;
pg_maxw = pg_width * (cols - 1);
}
int pg_scroll(n)
int n;
{
#ifndef TK
pg_line += n;
if (pg_line >= (Lines - 1)) {
pg_line = 0;
if (any_key(0) == K_interrupt)
return 1;
tputc(CR);
clrline();
}
#endif
return 0;
}
int pg_next()
{
int c;
if (batch_mode) {
putchar(NL);
return 0;
}
#ifndef TK
pg_line++;
if (pg_line < Lines) {
gotoxy(pg_col, pg_line);
if (pg_line == Lines - 1 && pg_col == pg_maxw) {
c = any_key(0);
if (c == '/') {
char *expr;
tputc(CR);
tputc('/');
clrline();
expr = get_s((char *)NULL, (char *)NULL, (char *)NULL, NULL_FCT);
if (expr != NULL && *expr != NUL) {
freeobj(pg_regexp);
pg_regexp = regcomp(expr);
pg_new_regexp = 1;
}
}
gotoxy(0, pg_fline);
clrpage();
pg_col = 0;
pg_line = pg_fline;
if (c == K_interrupt) {
pg_quit = 1;
return -1;
}
return 1;
}
} else {
pg_line = pg_fline;
pg_col += pg_width;
gotoxy(pg_col, pg_line);
}
#endif
return 0;
}
void
pg_indent(pos)
int pos;
{
int i;
BATCH_CHECK_V;
for (i=0; i<(pos - curxy_c + pg_col); i++)
tkb_c(' ');
gotoxy(pg_col + pos, pg_line);
}
int pg_end()
{
#ifndef TK
int c;
if (pg_quit == 0 && pg_next() == 0)
c = any_key(0);
else
c = K_interrupt;
if (pg_regexp) {
freeobj(pg_regexp);
pg_regexp = NULL;
}
return c == K_interrupt ? -1 : 0;
#else
return 0;
#endif
}
void
user_delay(ticks)
int ticks;
{
BATCH_CHECK_V;
if (ticks <= 0 || conf_dont_sleep) {
tprintf(" <>");
any_key(10000);
} else {
fl;
sleep((unsigned)ticks);
}
}